package com.bibrApp.difu.actvity;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbEndpoint;
import android.hardware.usb.UsbInterface;
import android.hardware.usb.UsbManager;
import android.os.AsyncTask;
import android.os.Handler;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;

import com.bibrApp.difu.BeemIntent;
import com.bibrApp.difu.R;
import com.bibrApp.difu.actvity.fund_security_code_mvp.FundSecurityCodeActivity;
import com.bibrApp.difu.base.BaseActivity;
import com.bibrApp.difu.base.BasePresenter;
import com.bibrApp.difu.base.IBaseView;
import com.bibrApp.difu.utils.ClsPublicUtils;
import com.bibrApp.difu.utils.DialogUtils;
import com.bibrApp.difu.utils.IntentUtil;
import com.bibrApp.difu.utils.Protocol;
import com.bibrApp.difu.utils.StrValidateUtils;
import com.bibrApp.difu.utils.ToastUtils;
import com.bibrApp.difu.widget.DFDialog;
import com.google.protobuf.InvalidProtocolBufferException;
import com.satoshilabs.trezor.lib.protobuf.TrezorMessageCommon;
import com.satoshilabs.trezor.lib.protobuf.TrezorMessageManagement;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;

import butterknife.BindView;

public class ChangePinActivity extends BaseActivity<BasePresenter> implements IBaseView, View.OnClickListener {
    @BindView(R.id.num_7)
    ImageView num7;
    @BindView(R.id.num_8)
    ImageView num8;
    @BindView(R.id.num_9)
    ImageView num9;
    @BindView(R.id.num_4)
    ImageView num4;
    @BindView(R.id.num_5)
    ImageView num5;
    @BindView(R.id.num_6)
    ImageView num6;
    @BindView(R.id.num_1)
    ImageView num1;
    @BindView(R.id.num_2)
    ImageView num2;
    @BindView(R.id.num_3)
    ImageView num3;

    @BindView(R.id.btn_sure)
    Button sureBtn;
    @BindView(R.id.dialog_password_tv)
    TextView tvPwd;
    @BindView(R.id.dialog_del)
    ImageView IVdel;
    @BindView(R.id.dialog_title)
    TextView dialog_title;
    private Context mContext;

    private UsbManager usbManager;//usb管理器
    private UsbDevice mUsbDevice;//找到的usb设备
    private UsbInterface mUsbInterface;
    private UsbDeviceConnection mUsbDeviceConnection;
    private boolean isSecondSure;
    private Activity mActivity;

    @Override
    protected void initPresenter() {
        presenter = new BasePresenter(this, this);
        presenter.init();
    }

    @Override
    protected int getLayoutId() {
        return R.layout.activity_change_pin;
    }

    @Override
    public void initView() {
        mContext = this;
        mActivity = this;
        usbManager = (UsbManager) mContext.getSystemService(Context.USB_SERVICE);
        num1.setOnClickListener(this);
        num2.setOnClickListener(this);
        num3.setOnClickListener(this);
        num4.setOnClickListener(this);
        num5.setOnClickListener(this);
        num6.setOnClickListener(this);
        num7.setOnClickListener(this);
        num8.setOnClickListener(this);
        num9.setOnClickListener(this);
        IVdel.setOnClickListener(this);
        sureBtn.setOnClickListener(this);
        checkUsb();
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.num_1:
                changeNum(1);
                break;
            case R.id.num_2:
                changeNum(2);
                break;
            case R.id.num_3:
                changeNum(3);
                break;
            case R.id.num_4:
                changeNum(4);
                break;
            case R.id.num_5:
                changeNum(5);
                break;
            case R.id.num_6:
                changeNum(6);
                break;
            case R.id.num_7:
                changeNum(7);
                break;
            case R.id.num_8:
                changeNum(8);
                break;
            case R.id.num_9:
                changeNum(9);
                break;
            case R.id.dialog_del:
                if (sb.toString().length() > 0) {
                    sb.deleteCharAt(sb.length() - 1);
                }
                if (sb.toString().length() == 0) {
                    sureBtn.setEnabled(false);
                    sureBtn.setClickable(false);
                    tvPwd.setText("");
                } else {
                    pwdStr = sb.toString();
                    tvPwd.setText(StrValidateUtils.replaceAllStr(pwdStr));
                }
                break;
            case R.id.btn_sure:
                sendPin();
                break;
            default:
                break;
        }
    }

    private void checkUsb() {
        if (usbManager == null) {
            return;
        }
        HashMap<String, UsbDevice> deviceHashMap = usbManager.getDeviceList();
        Iterator<UsbDevice> deviceIterator = deviceHashMap.values().iterator();
        ArrayList<String> usbDeviceList = new ArrayList<>();//存放usb数量
        while (deviceIterator.hasNext()) {
            UsbDevice device = deviceIterator.next();
            usbDeviceList.add(String.valueOf(device.getVendorId()));
            usbDeviceList.add(String.valueOf(device.getProductId()));
            if (device.getVendorId() == 0x1209 && device.getProductId() == 0x53C1) {//找到我们的usb设备
                mUsbDevice = device;
            }
        }
        //请求权限
        if (mUsbDevice == null) {
            ToastUtils.ShowToast(mContext, "没找到对应的usb设备");
            return;
        }
        if (usbManager.hasPermission(mUsbDevice)) {
            findIntfAndEpt();
        } else {
            getUsbPermission(mUsbDevice);
        }
    }

    /**
     * 寻找接口和分配结点
     */
    private UsbEndpoint usbEndpointIn;
    private UsbEndpoint usbEndpointOut;

    private void findIntfAndEpt() {
        if (mUsbDevice == null) {
            ToastUtils.ShowToast(mContext, "没有找到相匹配的设备");
            return;
        }
        if (mUsbDevice.getInterfaceCount() <= 0) {
            return;
        }
        mUsbInterface = mUsbDevice.getInterface(0);
        //打开设备，获取UsbDeviceConnection对象，连接设备，用于后面的通讯
        UsbDeviceConnection usbDeviceConnection = usbManager.openDevice(mUsbDevice);
        if (usbDeviceConnection == null) {
            ToastUtils.ShowToast(mContext, "连接失败");
            return;
        }
        if (usbDeviceConnection.claimInterface(mUsbInterface, true)) {
            //找到接口
            mUsbDeviceConnection = usbDeviceConnection;
            //用于UsbDeviceConnection与UsbInterface进行端点设置和通讯
            if (mUsbInterface.getEndpoint(0) != null) {
                usbEndpointIn = mUsbInterface.getEndpoint(0);
            }
            if (mUsbInterface.getEndpoint(1) != null) {
                usbEndpointOut = mUsbInterface.getEndpoint(1);
            }
            initU();
        } else {
            //断开连接
            usbDeviceConnection.close();
        }
    }

    private void initU() {
        int ret = -100;
        TrezorMessageManagement.ChangePin.Builder changePingBuilder = TrezorMessageManagement.ChangePin.newBuilder();
        TrezorMessageManagement.ChangePin changePin = changePingBuilder.build();
        byte[] init = changePin.toByteArray();//转成16进制

        if (mUsbDeviceConnection == null) {
            ToastUtils.ShowToast(mContext, "没有建立连接");
            return;
        }
        //添加协议 changepin = 4
        List<byte[]> bytes = Protocol.encode(4, init);
        // 1,发送准备命令
        //通过usb hid传输数据给u盾
        for (int i = 0; i < bytes.size(); i++) {
            byte[] sendbytes = bytes.get(i);
            Log.d("dj", "==发送数据==" + ClsPublicUtils.bytesToHex(sendbytes));
            mUsbDeviceConnection.bulkTransfer(usbEndpointOut, sendbytes, sendbytes.length, 5000);
        }
        getHidMsg();
    }

    /**
     * 获取u盾的消息
     */
    @SuppressLint("StaticFieldLeak")
    public void getHidMsg() {
        new AsyncTask<String, Integer, List<byte[]>>() {
            @Override
            protected void onPreExecute() {
                super.onPreExecute();
                //开始接受信息
                DialogUtils.showDialog(mContext);
            }

            @Override
            protected List<byte[]> doInBackground(String... params) {
                List<byte[]> byteRe = new ArrayList<>();
                try {
                    boolean isContinue = true;
                    while (isContinue) {
                        byte[] recByte = new byte[64];
                        mUsbDeviceConnection.bulkTransfer(usbEndpointIn, recByte, recByte.length, 10000);
                        if (Protocol.hasHead(recByte)) {
                            byteRe.add(recByte);
                        } else {
                            isContinue = false;
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
                return byteRe;
            }

            @SuppressLint("NewApi")
            @Override
            protected void onPostExecute(List<byte[]> bytes) {
                if (bytes == null || bytes.size() == 0) {
                    //接受信息失败
                    DialogUtils.dismissDialog();
                    return;
                }
                DialogUtils.dismissDialog();
                Log.d("dj", "==解码=前=" + ClsPublicUtils.bytesToHex(bytes.get(0)));
                Log.d("dj", "==解码=后=" + Protocol.decode(bytes));
                try {
                    if (Protocol.getType(bytes) == 3) {//失败
                        TrezorMessageCommon.Failure failure = TrezorMessageCommon.Failure.parseFrom(ClsPublicUtils.hexToBytes(Protocol.decode(bytes)));
                        if (TrezorMessageCommon.Failure.FailureType.Failure_ActionCancelled == failure.getCode()) {//用户取消
                            ToastUtils.ShowToast(mContext, "用户取消操作");
                        }
                        ToastUtils.ShowToast(mContext, failure.getMessage());
                        finish();
                    } else if (Protocol.getType(bytes) == 26) {//确认ButtonRequest
                        ShowSureDialog();
                        sendSure();
                    } else if (Protocol.getType(bytes) == 18) {//PinMatrixRequest
                        if (dfDialogBuilder != null) {
                            dfDialogBuilder.dismiss();
                        }
                        TrezorMessageCommon.PinMatrixRequest pinMatrixRequest = TrezorMessageCommon.PinMatrixRequest.parseFrom(ClsPublicUtils.hexToBytes(Protocol.decode(bytes)));
                        if (pinMatrixRequest.getType() == TrezorMessageCommon.PinMatrixRequest.PinMatrixRequestType.PinMatrixRequestType_NewFirst) {//第一次输入
                            pwdStr = "";
                            tvPwd.setText("");
                        } else if (pinMatrixRequest.getType() == TrezorMessageCommon.PinMatrixRequest.PinMatrixRequestType.PinMatrixRequestType_NewSecond) {//第二次输入pin
                            pwdStr = "";
                            tvPwd.setText("");
                            dialog_title.setText("请再次输入PIN码");
                            isSecondSure = true;
                        }
                    } else if (Protocol.getType(bytes) == 2) {//成功
                        ToastUtils.ShowToast(mContext, "PIN码修改成功");
                        finish();
                    }
                } catch (InvalidProtocolBufferException e) {
                    e.printStackTrace();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }

        }.execute();
    }

    private DFDialog dfDialogBuilder;

    private void ShowSureDialog() {
        dfDialogBuilder = new DFDialog.Builder(mContext)
                .setTitle("提示")
                .setTwoBtnGone(true)
                .setDissMiss(true)
                .setMessage("请在设备上点击确认")
                .setSure(false)
                .show();
    }

    private void sendSure() {
        int ret = -100;
        TrezorMessageCommon.ButtonAck.Builder buttonAckBuilder = TrezorMessageCommon.ButtonAck.newBuilder();
        TrezorMessageCommon.ButtonAck changePin = buttonAckBuilder.build();
        byte[] init = changePin.toByteArray();//转成16进制

        if (mUsbDeviceConnection == null) {
            ToastUtils.ShowToast(mContext, "没有建立连接");
            return;
        }
        //添加协议 changepin = 4
        List<byte[]> bytes = Protocol.encode(27, init);
        // 1,发送准备命令
        //通过usb hid传输数据给u盾
        for (int i = 0; i < bytes.size(); i++) {
            byte[] sendbytes = bytes.get(i);
            Log.d("dj", "==发送数据==" + ClsPublicUtils.bytesToHex(sendbytes));
            mUsbDeviceConnection.bulkTransfer(usbEndpointOut, sendbytes, sendbytes.length, 5000);
        }
        //死循环接受消息
        getMsg();
    }

    private boolean isDestory = true;
    private static Handler mHandler = new Handler();

    private void getMsg() {
        new Thread(() -> {
            do {
                List<byte[]> byteRe = new ArrayList<>();
                try {
                    boolean isContinue = true;
                    while (isContinue) {
                        byte[] recByte = new byte[64];
                        mUsbDeviceConnection.bulkTransfer(usbEndpointIn, recByte, recByte.length, 10000);
                        if (Protocol.hasHead(recByte)) {
                            byteRe.add(recByte);
                        } else {
                            isContinue = false;
                        }
                    }

                    if (byteRe.size() > 0) {
                        if (Protocol.getType(byteRe) == 18) {//PinMatrixRequest
                            mHandler.postDelayed(() -> {
                                if (dfDialogBuilder != null) {
                                    dfDialogBuilder.dismiss();
                                }
                                isDestory = false;
                            }, 100);
                        } else {
                            finish();
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            } while (isDestory);
        }).start();
    }

    private void sendPin() {
        int ret = -100;
        TrezorMessageCommon.PinMatrixAck.Builder pinAckBuilder = TrezorMessageCommon.PinMatrixAck.newBuilder();
        pinAckBuilder.setPin(pwdStr);
        TrezorMessageCommon.PinMatrixAck pinMatrixAck = pinAckBuilder.build();
        byte[] init = pinMatrixAck.toByteArray();//转成16进制

        if (mUsbDeviceConnection == null) {
            ToastUtils.ShowToast(mContext, "没有建立连接");
            return;
        }
        //添加协议 PinMatrixAck = 19
        List<byte[]> bytes = Protocol.encode(19, init);
        // 1,发送准备命令
        //通过usb hid传输数据给u盾
        for (int i = 0; i < bytes.size(); i++) {
            byte[] sendbytes = bytes.get(i);
            Log.d("dj", "==发送数据==" + ClsPublicUtils.bytesToHex(sendbytes));
            mUsbDeviceConnection.bulkTransfer(usbEndpointOut, sendbytes, sendbytes.length, 5000);
        }
        getHidMsg();
    }

    StringBuilder sb = new StringBuilder();
    String pwdStr;

    private void changeNum(int num) {
        if (sb.toString().length() < 9) {
            sb.append(num);
            pwdStr = sb.toString();
            tvPwd.setText(StrValidateUtils.replaceAllStr(pwdStr));
        }
        sureBtn.setEnabled(true);
        sureBtn.setClickable(true);
    }


    private Receiver mUsbReceiver;

    //开始申请USB权限
    private void getUsbPermission(UsbDevice mUSBDevice) {
        PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(BeemIntent.ACTION_USB_INTENT), 0);
        IntentFilter filter = new IntentFilter(BeemIntent.ACTION_USB_INTENT);
        filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
        filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
        mUsbReceiver = new Receiver();
        mContext.registerReceiver(mUsbReceiver, filter);
        usbManager.requestPermission(mUSBDevice, pendingIntent); // 该代码执行后，系统弹出一个对话框/等待权限
    }

    private class Receiver extends BroadcastReceiver {
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();

            if (BeemIntent.ACTION_USB_INTENT.equals(action)) {
                synchronized (this) {
                    UsbDevice device = (UsbDevice) intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
                    if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)
                            && mUsbDevice.equals(device)) {
                        //TODO 授权成功，操作USB设备
                        ToastUtils.ShowToast(mContext, "usb授权成功");
                    } else {
                        //用户点击拒绝了
                        ToastUtils.ShowToast(mContext, "拒绝usb授权");
                    }
                }
            }
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        isDestory = false;
    }
}
